/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * EventActionPanel.java
 *
 * Created on 24-mrt-2010, 8:07:06
 */
package nl.lemval.nododue.component;

import java.awt.Component;
import java.awt.Font;
import java.awt.event.KeyListener;
import java.util.Collection;
import java.util.Set;
import javax.swing.JLabel;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import nl.lemval.nododue.NodoDueManager;
import nl.lemval.nododue.Options;
import nl.lemval.nododue.cmd.CommandDeviceInfo;
import nl.lemval.nododue.cmd.CommandInfo;
import nl.lemval.nododue.cmd.NodoCommand;
import nl.lemval.nododue.cmd.Parameter;
import nl.lemval.nododue.tabs.NodoBasePanel;
import nl.lemval.nododue.util.Device;
import nl.lemval.nododue.util.listeners.HexKeyListener;
import nl.lemval.nododue.util.listeners.KakuKeyListener;
import nl.lemval.nododue.util.listeners.StatusMessageListener;
import org.jdesktop.application.Action;

/**
 *
 * @author Michael
 */
public class EventActionPanel extends NodoBasePanel {

    private DefaultComboBoxModel model;
    private DefaultComboBoxModel commandData1Model;
    private DefaultComboBoxModel commandData2Model;
    private boolean autoUnit = false;
    private HexKeyListener hkl = new HexKeyListener(2);
    private KakuKeyListener kkl = new KakuKeyListener();
    private Font explanationFont = Font.decode(null);

    /** Creates new form EventActionPanel */
    public EventActionPanel(StatusMessageListener view, String name) {
        super(view);
        model = new DefaultComboBoxModel();
        commandData1Model = new DefaultComboBoxModel();
        commandData2Model = new DefaultComboBoxModel();
        explanationFont = Options.getInstance().getBaseFont();
        explanationFont = explanationFont.deriveFont(explanationFont.getSize()-1);

        initComponents();

        nameLabel.setText(name);
        model.insertElementAt(getResourceString("commandName.select"), 0);
        data1.getEditor().getEditorComponent().addKeyListener(hkl);
        data2.getEditor().getEditorComponent().addKeyListener(hkl);
        nodoCommandList.setSelectedIndex(0);
        nodoCommandList.getEditor().getEditorComponent().addKeyListener(
                new HexKeyListener(4));
   }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        nameLabel = new javax.swing.JLabel();
        nodoCommandList = new javax.swing.JComboBox();
        nodoCommandInfoLabel = new javax.swing.JTextArea();
        nodoParameterLabel1 = new javax.swing.JLabel();
        jPanel1 = new javax.swing.JPanel();
        unitLabel = new javax.swing.JLabel();
        changeUnit = new javax.swing.JButton();
        data1Label = new javax.swing.JLabel();
        data1 = new javax.swing.JComboBox();
        data2Label = new javax.swing.JLabel();
        data2 = new javax.swing.JComboBox();
        kakuParm = new javax.swing.JToggleButton();
        jScrollPane1 = new javax.swing.JScrollPane();
        explanationText = new javax.swing.JTextArea();

        setName("Form"); // NOI18N

        nameLabel.setFont(nameLabel.getFont().deriveFont(nameLabel.getFont().getStyle() | java.awt.Font.BOLD, nameLabel.getFont().getSize()+1));
        org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(nl.lemval.nododue.NodoDueManager.class).getContext().getResourceMap(EventActionPanel.class);
        nameLabel.setText(resourceMap.getString("nameLabel.text")); // NOI18N
        nameLabel.setName("nameLabel"); // NOI18N

        nodoCommandList.setModel(model);
        nodoCommandList.setName("nodoCommandList"); // NOI18N
        nodoCommandList.addItemListener(new java.awt.event.ItemListener() {
            public void itemStateChanged(java.awt.event.ItemEvent evt) {
                nodoCommandListItemStateChanged(evt);
            }
        });

        nodoCommandInfoLabel.setEditable(false);
        nodoCommandInfoLabel.setFont(explanationFont);
        nodoCommandInfoLabel.setLineWrap(true);
        nodoCommandInfoLabel.setRows(3);
        nodoCommandInfoLabel.setTabSize(0);
        nodoCommandInfoLabel.setText(resourceMap.getString("nodoCommandInfoLabel.text")); // NOI18N
        nodoCommandInfoLabel.setWrapStyleWord(true);
        nodoCommandInfoLabel.setBorder(javax.swing.BorderFactory.createMatteBorder(1, 1, 1, 1, resourceMap.getColor("nodoCommandInfoLabel.border.matteColor"))); // NOI18N
        nodoCommandInfoLabel.setFocusable(false);
        nodoCommandInfoLabel.setName("nodoCommandInfoLabel"); // NOI18N
        nodoCommandInfoLabel.setRequestFocusEnabled(false);

        nodoParameterLabel1.setFont(nodoParameterLabel1.getFont().deriveFont(nodoParameterLabel1.getFont().getStyle() | java.awt.Font.BOLD, nodoParameterLabel1.getFont().getSize()+1));
        nodoParameterLabel1.setText(resourceMap.getString("nodoParameterLabel1.text")); // NOI18N
        nodoParameterLabel1.setName("nodoParameterLabel1"); // NOI18N

        jPanel1.setName("jPanel1"); // NOI18N

        unitLabel.setText(resourceMap.getString("unitLabel.text")); // NOI18N
        unitLabel.setName("unitLabel"); // NOI18N

        javax.swing.ActionMap actionMap = org.jdesktop.application.Application.getInstance(nl.lemval.nododue.NodoDueManager.class).getContext().getActionMap(EventActionPanel.class, this);
        changeUnit.setAction(actionMap.get("selectUnits")); // NOI18N
        changeUnit.setText(resourceMap.getString("changeUnit.text")); // NOI18N
        changeUnit.setName("changeUnit"); // NOI18N

        data1Label.setText(resourceMap.getString("data1Label.text")); // NOI18N
        data1Label.setName("data1Label"); // NOI18N

        data1.setEditable(true);
        data1.setModel(commandData1Model);
        data1.setMaximumSize(new java.awt.Dimension(123, 20));
        data1.setName("data1"); // NOI18N

        data2Label.setText(resourceMap.getString("data2Label.text")); // NOI18N
        data2Label.setName("data2Label"); // NOI18N

        data2.setEditable(true);
        data2.setModel(commandData2Model);
        data2.setMaximumSize(new java.awt.Dimension(123, 20));
        data2.setName("data2"); // NOI18N

        kakuParm.setAction(actionMap.get("activateKakuInput")); // NOI18N
        kakuParm.setIcon(resourceMap.getIcon("kakuParm.icon")); // NOI18N
        kakuParm.setText(resourceMap.getString("kakuParm.text")); // NOI18N
        kakuParm.setToolTipText(resourceMap.getString("kakuParm.toolTipText")); // NOI18N
        kakuParm.setBorderPainted(false);
        kakuParm.setContentAreaFilled(false);
        kakuParm.setFocusPainted(false);
        kakuParm.setMargin(new java.awt.Insets(0, 2, 2, 2));
        kakuParm.setMaximumSize(new java.awt.Dimension(23, 23));
        kakuParm.setMinimumSize(new java.awt.Dimension(23, 23));
        kakuParm.setName("kakuParm"); // NOI18N
        kakuParm.setSelectedIcon(resourceMap.getIcon("kakuParm.selectedIcon")); // NOI18N

        org.jdesktop.layout.GroupLayout jPanel1Layout = new org.jdesktop.layout.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(org.jdesktop.layout.GroupLayout.TRAILING, jPanel1Layout.createSequentialGroup()
                .add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING, false)
                    .add(unitLabel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 75, Short.MAX_VALUE)
                    .add(data2Label, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .add(data1Label, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, 18, Short.MAX_VALUE)
                .add(kakuParm, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING, false)
                    .add(org.jdesktop.layout.GroupLayout.TRAILING, data2, 0, 0, Short.MAX_VALUE)
                    .add(changeUnit, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .add(data1, 0, 99, Short.MAX_VALUE)))
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(jPanel1Layout.createSequentialGroup()
                .add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                    .add(changeUnit)
                    .add(unitLabel))
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(kakuParm, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                    .add(jPanel1Layout.createSequentialGroup()
                        .add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                            .add(data1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                            .add(data1Label))
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                            .add(data2, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                            .add(data2Label)))))
        );

        jScrollPane1.setName("jScrollPane1"); // NOI18N

        explanationText.setBackground(resourceMap.getColor("explanationText.background")); // NOI18N
        explanationText.setColumns(20);
        explanationText.setEditable(false);
        explanationText.setFont(explanationFont);
        explanationText.setLineWrap(true);
        explanationText.setRows(5);
        explanationText.setText(resourceMap.getString("explanationText.text")); // NOI18N
        explanationText.setWrapStyleWord(true);
        explanationText.setName("explanationText"); // NOI18N
        jScrollPane1.setViewportView(explanationText);

        org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(layout.createSequentialGroup()
                .addContainerGap()
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(layout.createSequentialGroup()
                        .add(nodoParameterLabel1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 133, Short.MAX_VALUE)
                        .add(100, 100, 100))
                    .add(layout.createSequentialGroup()
                        .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING, false)
                            .add(org.jdesktop.layout.GroupLayout.LEADING, nodoCommandInfoLabel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 223, Short.MAX_VALUE)
                            .add(org.jdesktop.layout.GroupLayout.LEADING, nameLabel)
                            .add(org.jdesktop.layout.GroupLayout.LEADING, nodoCommandList, 0, 223, Short.MAX_VALUE))
                        .addContainerGap())
                    .add(org.jdesktop.layout.GroupLayout.TRAILING, layout.createSequentialGroup()
                        .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING)
                            .add(org.jdesktop.layout.GroupLayout.LEADING, jScrollPane1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 223, Short.MAX_VALUE)
                            .add(jPanel1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                        .addContainerGap())))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(layout.createSequentialGroup()
                .addContainerGap()
                .add(nameLabel)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(nodoCommandList, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(nodoCommandInfoLabel, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 51, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(nodoParameterLabel1)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(jPanel1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(jScrollPane1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 130, Short.MAX_VALUE)
                .addContainerGap())
        );
    }// </editor-fold>//GEN-END:initComponents

    private void nodoCommandListItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_nodoCommandListItemStateChanged
        if ( evt.getStateChange() == evt.DESELECTED ) {
            return;
        }
        // Update the data models.
        JComboBox cb = (JComboBox) evt.getSource();
        Object selected = cb.getSelectedItem();
        if ( selected instanceof CommandInfo ) {
            CommandInfo cmd = (CommandInfo) selected;
            if ( CommandInfo.CUSTOM_CMD.equals(cmd.getName()) ) {
                nodoCommandList.setEditable(true);
                // Do not use setSelectedItem
                nodoCommandList.getEditor().setItem(getResourceString("custom_example"));
            } else {
                nodoCommandList.setEditable(false);
            }
            if ( CommandInfo.Name.SendKAKU.name().equals(cmd.getName())
		    || CommandInfo.Name.KAKU.name().equals(cmd.getName()) ) {
                kakuParm.setSelected(true);
                kakuParm.setVisible(true);
            } else {
                kakuParm.setSelected(false);
                kakuParm.setVisible(false);
            }
            activateKakuInput();
            
            Parameter d1 = cmd.getParameter(0);
            init(d1, data1, data1Label, commandData1Model, "dataText1");
            Parameter d2 = cmd.getParameter(1);
            init(d2, data2, data2Label, commandData2Model, "dataText2");
            nodoCommandInfoLabel.setText(cmd.getDescription());
            explanationText.setText(cmd.getExplanation());
            explanationText.setCaretPosition(0);
        } else {
            nodoCommandList.setEditable(false);
            kakuParm.setSelected(false);
            kakuParm.setVisible(false);
            activateKakuInput();

            // Check if it is a value for custom
            String value = (String) selected;
            if ( value != null && value.length() > 0 ) {
                String result = hkl.toHexValue(value);
                if ( result != null )
                    return;
            }
            data1Label.setText(getResourceString("dataText1.text"));
            data1.setEnabled(false);
            commandData1Model.removeAllElements();
            data2Label.setText(getResourceString("dataText2.text"));
            data2.setEnabled(false);
            commandData2Model.removeAllElements();
            nodoCommandInfoLabel.setText(null);
            explanationText.setText(null);
        }
}//GEN-LAST:event_nodoCommandListItemStateChanged

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton changeUnit;
    private javax.swing.JComboBox data1;
    private javax.swing.JLabel data1Label;
    private javax.swing.JComboBox data2;
    private javax.swing.JLabel data2Label;
    private javax.swing.JTextArea explanationText;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JToggleButton kakuParm;
    private javax.swing.JLabel nameLabel;
    private javax.swing.JTextArea nodoCommandInfoLabel;
    private javax.swing.JComboBox nodoCommandList;
    private javax.swing.JLabel nodoParameterLabel1;
    private javax.swing.JLabel unitLabel;
    // End of variables declaration//GEN-END:variables

    public void addAll(Collection<CommandInfo> eventActions) {
        for (CommandInfo eventAction : eventActions) {
           model.addElement(eventAction);
        }
    }

    public NodoCommand getSelectedItem() {
        Object obj =  model.getSelectedItem();
        if ( obj instanceof CommandDeviceInfo ) {
	    CommandDeviceInfo cdi = (CommandDeviceInfo) obj;
            NodoCommand cmd = new NodoCommand(cdi.getDevice());
            if ( autoUnit == false ) {
                cmd.makeDistributed();
            }
            return cmd;
        }
        
        if ( obj instanceof CommandInfo ) {
	    CommandInfo ci = (CommandInfo) obj;
            String d1 = (String) data1.getSelectedItem();
            String v1 = null;
            if ( kakuParm.isSelected() ) {
                if ( !kkl.checkValue(d1) ) {
                    NodoDueManager.showMessage("command_invalid", ci.getName());
                    return null;
                }
                v1 = d1;
            } else {
                v1 = ci.getParameter(0).getValue(d1);
            }

            String d2 = (String) data2.getSelectedItem();
            String v2 = ci.getParameter(1).getValue(d2);

            NodoCommand cmd = new NodoCommand(ci, v1, v2);
            if ( autoUnit == false ) {
                cmd.makeDistributed();
            }
            return cmd;
        }
        String value = (String) obj;
        if ( value != null && value.length() > 0 ) {
            String result = hkl.toHexValue(value);
            if ( result != null ) {
                String d1 = (String) data1.getSelectedItem();
                String d2 = (String) data2.getSelectedItem();
                NodoCommand cmd = NodoCommand.getCustomCommand(result, hkl.toHexValue(d1), hkl.toHexValue(d2));
                if ( autoUnit == false ) {
                    cmd.makeDistributed();
                }
                return cmd;
            }
        }
        return null;
    }

    public void setAutoUnit(boolean value) {
        autoUnit = value;
        if ( autoUnit ) {
            changeUnit.setEnabled(false);
            unitLabel.setVisible(false);
            changeUnit.setVisible(false);
        }
    }

    private void init(Parameter parm, JComboBox box, JLabel label, DefaultComboBoxModel model, String resource) {
        model.removeAllElements();
        box.getEditor().setItem(null);
        if ( parm == null || parm.getName() == null || parm.getName().trim().length() == 0 ) {
            box.setEnabled(false);
            label.setText(getResourceString(resource + ".text"));
        } else {
            box.setEnabled(true);
            label.setText(parm.getName());
            String[] names = parm.getValueNames();
            if ( names.length > 1 ) {
                box.setEditable(false);
            } else {
                box.setEditable(true);
            }
            for (int i = 0; i < names.length; i++) {
                model.addElement(names[i]);
            }
        }
    }

    @Action
    public void selectUnits() {
        NodoDueManager.getApplication().getView().showUnitSelectionBox(false);
    }

    public void setSelected(NodoCommand cmd) {

        // First check for an appliance
        Device appliance = Options.getInstance().getAppliance(cmd.toString());
        if ( appliance != null) {
            for (int i = 0; i < nodoCommandList.getItemCount(); i++) {
                Object obj = nodoCommandList.getItemAt(i);
                if ( obj instanceof CommandInfo ) {
                    CommandInfo info = (CommandInfo) obj;
                    if ( info.getName().equals(CommandDeviceInfo.getName(appliance)) ) {
                        nodoCommandList.setSelectedIndex(i);
                        return;
                    }
                }
            }
        }

        for (int i = 0; i < nodoCommandList.getItemCount(); i++) {
            Object obj = nodoCommandList.getItemAt(i);

            if ( obj instanceof CommandDeviceInfo ) {
                if ( cmd.matches(((CommandDeviceInfo) obj).getDevice()) ) {
                    nodoCommandList.setSelectedIndex(i);
                    return;
                }
            }

            if ( obj instanceof CommandInfo ) {
                CommandInfo info = (CommandInfo) obj;

                if ( appliance != null ) {
                    if ( info.getName().equals(CommandDeviceInfo.getName(appliance)) ) {
                        nodoCommandList.setSelectedIndex(i);
                        return;
                    }
                }

                if ( cmd.getName().equals(info.getName()) ) {
                    nodoCommandList.setSelectedIndex(i);
                    String val1 = info.getParameter(0).getValueName(cmd.getData1());
                    String val2 = info.getParameter(1).getValueName(cmd.getData2());
                    data1.setSelectedItem(val1);
                    data2.setSelectedItem(val2);
                    return;
                }
            }
        }
    }

    @Action
    public void activateKakuInput() {
        Component edcomp = data1.getEditor().getEditorComponent();
        KeyListener[] listeners = edcomp.getKeyListeners();
        for (int i = 0; i < listeners.length; i++) {
            edcomp.removeKeyListener(listeners[i]);
        }
        if ( kakuParm.isSelected() ) {
            edcomp.addKeyListener(kkl);
        } else {
            edcomp.addKeyListener(hkl);
        }
    }

    public void updateAppliances() {
        for (int i = 0; i < model.getSize(); i++) {
            Object object = model.getElementAt(i);
            if ( object instanceof CommandDeviceInfo ) {
                model.removeElementAt(i);
                i--;
            }
        }
        Set<Device> applicances = Options.getInstance().getApplicances();
        for (Device device : applicances) {
            if ( device.isActive() ) {
                CommandInfo info = new CommandDeviceInfo(device);
                model.addElement(info);
            }
        }
    }
}
